package cn.com.ejiakanghu.web.alimini;/**
 * Created by Jhonbo on 2018/5/10.
 */

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipayEncrypt;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import org.apache.commons.lang3.StringUtils;
import org.linlinjava.litemall.core.util.JacksonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * 支付宝小程序登录验证
 *
 * @author houzhibin
 * @create 2018-05-10 20:22
 */
public class AliAuthLoginUtil {
    public static Logger logger = LoggerFactory.getLogger(AliAuthLoginUtil.class);

    public static Map<String,Object> loginAuthGetAccessToken(String authCode) throws AlipayApiException {
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",AliMiniConfig.ALI_MINI_APP_ID,AliMiniConfig.ALI_PRIVATE_KEY,"json","UTF-8",AliMiniConfig.ALI_PUBLIC_KEY,"RSA2");
        AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
        request.setGrantType("authorization_code");
        request.setCode(authCode);
        AlipaySystemOauthTokenResponse response = alipayClient.execute(request);
        if(response.isSuccess()){
            logger.debug("------------->AliAuthSuc--{}",response.getAlipayUserId());
            Map<String,Object> userInfoMap = new HashMap<>();
            userInfoMap.put("aliUid",response.getUserId());
            userInfoMap.put("aliPayUid",response.getAlipayUserId());
            return userInfoMap;
        } else {
            logger.debug("------------->AliAuthFail--{}", JacksonUtil.gson.toJson(response));
            return null;
        }
    }

    /**
     *
     * @param response 小程序前端提交的
     * @return
     */
    public static String decryptStr(String response) throws Exception {
//1. 获取验签和解密所需要的参数
        Map<String, String> openapiResult = JSON.parseObject(response,
                new TypeReference<Map<String, String>>() {
                }, Feature.OrderedField);
        String signType = StringUtils.defaultIfBlank(openapiResult.get("signType"), "RSA2");
        String charset = StringUtils.defaultIfBlank(openapiResult.get("charset"), "UTF-8");
        String encryptType = StringUtils.defaultIfBlank(openapiResult.get("encryptType"), "AES");
        String sign = openapiResult.get("sign");
        String content = openapiResult.get("response");
//如果密文的
        boolean isDataEncrypted = !content.startsWith("{");
        boolean signCheckPass = false;

//2. 验签
        String signContent = content;
//如果是加密的报文则需要在密文的前后添加双引号
        if (isDataEncrypted) {
            signContent = "\"" + signContent + "\"";
        }
        try {
            signCheckPass = AlipaySignature.rsaCheck(signContent, sign, AliMiniConfig.ALI_PUBLIC_KEY, charset, signType);
        } catch (AlipayApiException e) {
            //验签异常, 日志
            logger.error("验签失败:{},{},{},{},{},{}",new Object[]{e.getErrCode(),e.getErrMsg(),charset,signType,sign,signContent});
        }
        if(!signCheckPass) {
            //验签不通过（异常或者报文被篡改），终止流程（不需要做解密）
            throw new Exception("验签失败");
        }

//3. 解密
        String plainData = null;
        if (isDataEncrypted) {
            try {
                plainData = AlipayEncrypt.decryptContent(content, encryptType, AliMiniConfig.ALI_DATA_ENCRYPT_KEY, charset);
            } catch (AlipayApiException e) {
                //加密异常, 日志
                throw new Exception("解密异常");
            }
        } else {
            plainData = content;
        }
        return plainData;
    }


    public static void main(String[] args) throws Exception {
        System.out.println(decryptStr("{\"response\":\"naxjCcxF2BCK2Jda7VcFWEbGTsr4U6dsQ2dWi3cKS5pqwLdQpp/v/cy0w52XGU4iTwLWPrbwCyYGLqV4tCCcl8h76W1fomGUIl1E/pLNRG8mOLdjAmnO1mB+BPyOzjqltHo2YzEAMVROo0UiQ04EjiSOeqI7Ju0nBxtEBP+rTJxEe/VcFMs1ZxpKN3FXJKE9fgUuqP5Tz6P7HHmEYBeYq+zQCwM/B+AV8SRVyyNwjC8+DJkjrdJNJAOVg9qzyzNp\",\"sign\":\"gOYbnFUw/0LB7gesQMnTv/l74Bet1ZxIV8ZOGojWicpa20g94QMW5O3AiqKITC0qL3ATy/IUIwRjl6InRteXZ0FnuHy/MuHjzCYocJIX3Ef78uCWrfg/802q+GbQ0YTdvcQz0CCMG7HedD6lkLf+j461T4wOIQTffn46TuA9yBSO9rO9d/cd9uGdJuISuckzmnHiT86vmzRvSGiyS4TMcaOFqE0b9mw/aaOgCbnjGxq9DM5EKfZXcivAFd/gq9ZZ/o0DPKJZSe+Gr3r9xjHrWXe9KJpmQ48K/ly7oMhuayoSigsHq3CBCNanZnvhZY+/oNiY68rpDWfusEYziCNqLA==\"}"));
    }
}
